﻿#region License
/*
Copyright (c) 2009, G.W. van der Vegt
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided 
that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the 
  following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 
  the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of G.W. van der Vegt nor the names of its contributors may be 
  used to endorse or promote products derived from this software without specific prior written 
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/
#endregion License

#region changelog

//----------   ---   -------------------------------------------------------------------------------
//Purpose:           Nestable WaitCursor based on IDisplosable
//By:                G.W. van der Vegt (wvd_vegt@knoware.nl)
//Url:               http://swiss.codeplex.com
//Depends:           -
//License:           New BSD License
//----------   ---   -------------------------------------------------------------------------------
//dd-mm-yyyy - who - description
//----------   ---   -------------------------------------------------------------------------------
//dd-mm-yyyy   veg - Created.
//15-08-2010   veg - Added support for disabling control(s).
//----------  ----   -------------------------------------------------------------------------------
//dd-mm-yyyy  todo
//                 - .
//                 * .
//----------  ----   -------------------------------------------------------------------------------

#endregion changelog
namespace Swiss
{
    using System;
    using System.Windows.Forms;
    using System.Reflection;

    /// <summary>
    /// Nestable WaitCursor based on IDisposable
    /// 
    /// usage:
    /// 
    /// using (WaitCursor wc as new WaitCursor()) {
    ///   ..your code
    /// }
    /// 
    /// Because of the IDisplosable, the WaitCursor 
    /// automatically reverts back to the value it had 
    /// at the start of the using statement. A nice effect of
    /// this construct is that one can also use it nested like:
    ///
    /// using (WaitCursor wc1 as new WaitCursor()) {
    ///   ..your code
    ///   
    ///   using (WaitCursor wc2 as new WaitCursor()) {
    ///     ..more of your code
    ///   }
    /// }
    /// 
    /// The inner using statement can also be localed in another 
    /// method or even library without problems of a premature
    /// reverting to a non waitcursor.
    /// 
    /// The IDisposable should also be Exception proof.
    /// 
    /// If you specify a control that has a Enabled property 
    /// WaitCursor can also Disable it temporarily.
    /// </summary>
    public class WaitCursor : IDisposable
    // define class
    {
        //Private storage for replaced cursor. 
        //Assures that nested usage also works
        private Cursor fCursor;
        private Control fControl = null;
        private Boolean fEnable;

        //Change Mouse Cursor to Cursors.WaitCursor
        public WaitCursor()
            : this(Cursors.WaitCursor)
        {
        }

        //Change Mouse Cursor to Cursors.WaitCursor
        public WaitCursor(Control control)
            : this(Cursors.WaitCursor, control)
        {
        }

        //Change Mouse Cursor and Disable Control
        public WaitCursor(Cursor curs, Control control)
        {
            fCursor = Cursor.Current;

            Cursor.Current = curs;

            if (control != null)
            {
                PropertyInfo pi = control.GetType().GetProperty("Enabled");
                if (pi != null)
                {
                    fControl = control;

                    fEnable = (Boolean)pi.GetValue(fControl, null);

                    pi.SetValue(fControl, false, new Object[] { });

                    fControl.Update();
                }
            }
        }

        //Change Mouse Cursor
        public WaitCursor(Cursor curs)
            : this(curs, null)
        {
            //Nothing
        }

        //Change the Mouse Pointer back to the Default
        public void Dispose()
        {
            Cursor.Current = fCursor;

            if (fControl != null)
            {
                PropertyInfo pi = fControl.GetType().GetProperty("Enabled");
                if (pi != null)
                {
                    pi.SetValue(fControl, fEnable, new Object[] { });

                    fControl.Update();

                    fControl = null;
                }
            }
        }
    }
}
